package com.zjp.reflect;

import com.zjp.entity.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author: zjp
 * @date: 2023-12-01
 * @description: 测试获取类的构造器
 */
public class Test2_GetConstructor {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 1.首先要获取类的 Class 对象
        Class<User> clazz = User.class;

        System.out.println("1.getConstructors：只能获取public的，不推荐使用");
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());// 构造器名称
            System.out.println(constructor.getParameterCount());// 参数数量
        }

        System.out.println("2.getConstructor： 只能获取public的，不推荐使用");
//        Constructor<User> noArgumentConstrocter = clazz.getConstructor(); // 获取无参构造器，报错，因为用了 private 修饰
//        System.out.println(noArgumentConstrocter.getName());
//        System.out.println(noArgumentConstrocter.getParameterCount());

        System.out.println("3.getDeclaredConstructors：可以获取所有构造器，推荐使用");
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            System.out.println(constructor.getName());// 构造器名称
            System.out.println(constructor.getParameterCount());// 参数数量
        }

        System.out.println("4.declaredConstructor：获取指定参数类型的构造器，可以获取private修饰的构造器");
        // 获取带参数的构造器
        Constructor<User> allArgsConstructor = clazz.getDeclaredConstructor(Integer.class, String.class);
//        System.out.println(allArgsConstructor.getName());
//        System.out.println(allArgsConstructor.getParameterCount());

        // 获取空参构造器
        Constructor<User> noArgConstructor = clazz.getDeclaredConstructor();
        System.out.println("---------------测试使用获得的构造器初始化对象---------------");
        noArgConstructor.setAccessible(true); // 因为构造器使用了 private 修饰，所以需要放开访问权限
        allArgsConstructor.setAccessible(true);
        User user = noArgConstructor.newInstance(); // 使用空参构造器创建对象
        User userZjp = allArgsConstructor.newInstance(1, "zjp"); // 使用带参构造器创建对象
        System.out.println(user);
        System.out.println(userZjp);
    }
}
